#include "ads1299_lowlevel.h"
#include <SPI.h>

// 全局变量及常量定义
int stat_1 = 0, stat_2 = 0;
long channelData[16];
const float V_REF = 2.5;      // 内部参考电压（单位：V）
const long ADC_MAX = 8388607; // 24位ADC最大正值 (2^23 - 1)
const int PGA = 1;
const float LSB = 6.246e-7;   // 对应增益PGA=1时的最小有效位电压

// ESP32SPI初始化设置
void ADS1299_SPI_init()
{
  // 绑定 SPI 总线到指定的 GPIO 引脚
  SPI.begin(HSPI_CLK, HSPI_MISO, HSPI_MOSI, CS);
  // 设置 SPI 的工作速度、数据传输顺序和时钟模式
  SPI.setBitOrder(MSBFIRST);
  SPI.setFrequency(5000000);
  SPI.setDataMode(SPI_MODE1);
}


// 电源管理：将PWDN引脚设为高电平（或根据设计要求操作）
void powerdown(){
  pinMode(PWDN, OUTPUT);
  digitalWrite(PWDN, HIGH);
  delay(100);
}

// 复位ADS1299：拉低RESET引脚一段时间再释放
void resetADS1299() {
  delay(20);
  pinMode(RESET, OUTPUT);
  digitalWrite(RESET, LOW);
  delayMicroseconds(10);
  digitalWrite(RESET, HIGH);
  delayMicroseconds(20);
}

// 退出连续数据传输模式（发送SDATAC命令）
void ADS1299_StopContinuousMode() {
  digitalWrite(CS, LOW);
  SPI.transfer(SDATAC);
  delay(10);
  digitalWrite(CS, HIGH);
}

// 启动转换（发送START命令）
void _START(){
  digitalWrite(CS, LOW);
  SPI.transfer(START_CMD);
  digitalWrite(CS, HIGH);
}

// 写寄存器：将指定寄存器写入一个字节数据
void WriteRegister(uint8_t regAddress, uint8_t value) {
  digitalWrite(CS, LOW);
  delayMicroseconds(2);
  SPI.transfer(WREG | regAddress);
  SPI.transfer(0x00); // 写1个寄存器(数量-1)
  SPI.transfer(value);
  delayMicroseconds(2);
  digitalWrite(CS, HIGH);
  delay(10);
}

// 读取寄存器：读取一个寄存器的值并打印（用于调试）
void ReadRegister(uint8_t regAddress) {
  uint8_t regValue;
  digitalWrite(CS, LOW);
  SPI.transfer(RREG | regAddress);
  SPI.transfer(0x00);
  delay(5);
  regValue = SPI.transfer(0x00);
  digitalWrite(CS, HIGH);
  delayMicroseconds(2);
  Serial.print("Register 0x");
  Serial.print(regAddress, HEX);
  Serial.print(": 0x");
  Serial.println(regValue, HEX);
}

// 读取多个寄存器数据
void ADS1299_ReadRegisters(uint8_t startAddress, uint8_t numRegisters) {
  digitalWrite(CS, LOW); // 拉低 CS 引脚，开始通信
  SPI.transfer(RREG | startAddress);// 发送 RREG 命令和起始地址
  SPI.transfer(numRegisters - 1);// 发送寄存器数量 - 1
  uint8_t regValues[17] = {0};
  for (uint8_t i = 0; i < numRegisters; i++) {
    regValues[i] = SPI.transfer(0x00); // 读取返回的寄存器数据
    delay(1);
  }
  digitalWrite(CS, HIGH);  // 拉高 CS 引脚，结束通信
  // 打印读取的寄存器值
  for (uint8_t i = 0; i < numRegisters; i++) {
    Serial.print("Register 0x");
    Serial.print(startAddress + i, HEX);  // 输出寄存器地址
    Serial.print(": 0x");
    Serial.println(regValues[i], BIN);  // 输出寄存器值
  }
}

// 读取数据（单次读取模式）: 发送RDATA命令并读取8通道的24位数据
void _RDATA() {  
  byte inByte;
  int nchan = 8;
  stat_1 = 0;
  stat_2 = 0;
  digitalWrite(CS, LOW);
  SPI.transfer(RDATA);
  delayMicroseconds(2);
  // 读取状态寄存器的3字节数据
  for (int i = 0; i < 3; i++) {
    inByte = SPI.transfer(0x00);
    stat_1 = (stat_1 << 8) | inByte;
  }
  // 读取8个通道数据，每个通道24位
  for (int i = 0; i < 8; i++) {
    channelData[i] = 0;
    for (int j = 0; j < 3; j++) {
      inByte = SPI.transfer(0x00);
      channelData[i] = (channelData[i] << 8) | inByte;
    }
  }
  digitalWrite(CS, HIGH);
  // 对24位数据进行符号扩展
  for (int i = 0; i < nchan; i++) {
    if (bitRead(channelData[i], 23) == 1) {
      channelData[i] |= 0xFF000000;
    } else {
      channelData[i] &= 0x00FFFFFF;
    }
  }
}


// 进入连续读取模式（发送RDATAC命令）
void _RDATAC() {
  digitalWrite(CS, LOW);
  SPI.transfer(RDATAC);
  digitalWrite(CS, HIGH);
  delayMicroseconds(3);
}

// 从 ADS1299 中读取数据并转换为电压值，然后打印出第 8 个通道（数组下标 7）的转换结果
void updateChannelData() {
    byte inByte;
    int nchan = 8; // Assume 8 channels by default
    digitalWrite(CS, LOW); // Open SPI communication
    // READ CHANNEL DATA FROM FIRST ADS IN DAISY LINE
    for (int i = 0; i < 3; i++) { // Read 3-byte status register from ADS 1
        inByte = SPI.transfer(0x00);
        stat_1 = (stat_1 << 8) | inByte;
    }

    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 3; j++) { // Read 24 bits of channel data from 1st ADS in 8 3-byte chunks
            inByte = SPI.transfer(0x00);
            channelData[i] = (channelData[i] << 8) | inByte;
        }
    }

    digitalWrite(CS, HIGH);

    // Reformat the numbers to convert 3-byte 2's complement to 4-byte 2's complement
    for (int i = 0; i < nchan; i++) {
        if (bitRead(channelData[i], 23) == 1) { // Check if the 24th bit is set (negative number)
            channelData[i] |= 0xFF000000; // Extend the sign bit to 32 bits
        } else {
            channelData[i] &= 0x00FFFFFF; // Mask to ensure positive values are correct
        }
    }
    for(int i = 0;i<nchan;i++)
     {
        if(i!=7) continue;
        Serial.print("Channel ");
        Serial.print(i + 1);
        Serial.print(": ");
        float ans = channelData[i]*LSB;
        Serial.println(ans,6);
       //Serial.println(channelData[i]);
      }
}

// 初始化ADS1299芯片，并进入连续读取模式
void ADS1299_StartContinuousMode() {
  pinMode(CS, OUTPUT);
  pinMode(DRDY, INPUT);
  digitalWrite(CS, HIGH);
  ADS1299_SPI_init();
  powerdown();
  resetADS1299();
  delay(400); // 等待芯片稳定

  ADS1299_StopContinuousMode();
  
  // 配置寄存器
  WriteRegister(CONFIG1, 0b11010110);
  WriteRegister(CONFIG2, 0b11010010); //配置CONFIG2寄存器：内部测试信号
  WriteRegister(CONFIG3, 0b11101100); //配置CONFIG3寄存器：参考电压、偏置放大器
  WriteRegister(LOFF, 0x00);          //配置LOFF寄存器：导联脱落检测参数 
  //通道输入短路，增益1, MUX=001 (输入短路), PD=0
  WriteRegister(CH1SET, 0b10001000); 
  WriteRegister(CH2SET, 0b10001000);
  WriteRegister(CH3SET, 0b10001000);
  WriteRegister(CH4SET, 0b10001000);
  WriteRegister(CH5SET, 0b10001000);
  WriteRegister(CH6SET, 0b10001000);
  WriteRegister(CH7SET, 0b10001000);
  WriteRegister(CH8SET, 0b00000000);
  WriteRegister(BIAS_SENSP, 0x00);
  WriteRegister(BIAS_SENSN, 0x00);
  WriteRegister(LOFF_SENSP, 0x00);
  WriteRegister(LOFF_SENSN, 0x00);
  WriteRegister(MISC1, 0b00100000);  //SRB1连接到所有通道的负输入端
  WriteRegister(CONFIG4, 0b00000000);

  _START();  // 发送START命令开始转换
  _RDATAC(); // 进入连续读取模式
  delay(100);
}

// 读取ads1299ID
void ADS1299_GetDeviceID(){
  pinMode(CS, OUTPUT);
  pinMode(DRDY, INPUT);
  digitalWrite(CS, HIGH);

  powerdown();
  resetADS1299();
  delay(400); // 等待芯片稳定

  ADS1299_StopContinuousMode();

  ReadRegister(0x00);
  delay(100);
}





